package com.techsoul.common.security.handler;

import com.techsoul.common.core.enums.HttpStatusEnum;
import com.techsoul.common.core.exception.BaseException;
import com.techsoul.common.core.exception.DemoModeException;
import com.techsoul.common.core.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;


/**
 * 全局异常处理，作用在@RequestMapping上的所有异常都会被捕获
 *
 * annotations 使用注解定义处理异常的范围，例如：@ControllerAdvice(annotations = RestController.class)
 * basePackages 使用包名定义处理异常的范围，例如：basePackages = {"com.techsoul", "org.springframework"}
 *
 * @author liuen
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 默认异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Result handleException(HttpServletRequest request, Exception e) {
        log.error(HttpStatusEnum.ERROR.getMsg(), e);
//        return new Result(HttpStatusEnum.ERROR.getCode(), HttpStatusEnum.ERROR.getMsg(), e.getMessage());
        return new Result(HttpStatusEnum.ERROR.getCode(), HttpStatusEnum.ERROR.getMsg(), null);
    }

    /**
     * 自定义异常处理
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(BaseException.class)
    public Result handleBaseException(HttpServletRequest request, BaseException e) {
        log.error(e.getMessage(), e);
        return new Result(e.getCode(), e.getMessage(), null);
    }

    /**
     * 方法参数校验异常处理
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleHttpParamException(HttpServletRequest request, MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String errorMessage = bindingResult.getFieldErrors()
                .stream()
                .map(fieldError -> fieldError.getDefaultMessage())
                .collect(Collectors.joining("|"));
        log.error(HttpStatusEnum.PARAM_ILLEGAL_EXCEPTION.getMsg(), e);
//        return new Result(HttpStatusEnum.PARAM_ILLEGAL_EXCEPTION.getCode(), errorMessage, e.toString());
        return new Result(HttpStatusEnum.PARAM_ILLEGAL_EXCEPTION.getCode(), errorMessage, null);
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public Result handleNoFoundException(HttpServletRequest request, NoHandlerFoundException e) {
        log.error(e.getMessage(), e);
//        return new Result(HttpStatusEnum.NOT_FOUND.getCode(), HttpStatusEnum.NOT_FOUND.getMsg(), e.getMessage());
        return new Result(HttpStatusEnum.NOT_FOUND.getCode(), HttpStatusEnum.NOT_FOUND.getMsg(), null);
    }

    @ExceptionHandler(AccessDeniedException.class)
    public Result handleAuthorizationException(HttpServletRequest request, AccessDeniedException e) {
        log.error(e.getMessage(), e);
//        return new Result(HttpStatusEnum.FORBIDDEN.getCode(), "没有权限，请联系管理员授权", e.getMessage());
        return new Result(HttpStatusEnum.FORBIDDEN.getCode(), "没有权限，请联系管理员授权", null);
    }

    @ExceptionHandler(DemoModeException.class)
    public Result handleDemoModeException(HttpServletRequest request, DemoModeException e) {
//        return new Result(HttpStatusEnum.UNAUTHORIZED.getCode(), "演示模式，不允许操作", e.getMessage());
        return new Result(HttpStatusEnum.UNAUTHORIZED.getCode(), "演示模式，不允许操作", null);
    }

}
